from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import KBinsDiscretizer
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.tree import DecisionTreeRegressor
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
def modeling(real_time_data):
    #处理异常值
    #print(real_time_data)
    line=[]
    def dataclean(ele):#利用3σ法进行数据清洗
        a = real_time_data[ele].mean()
        b = real_time_data[ele].std()
        c=a-3*b,
        d=a+3*b
        df=real_time_data.loc[(real_time_data[ele] > d) | (real_time_data[ele] < c)]
        line.append(df.index.tolist())#查找异常值所在的行
        #print(line)
    def datachoice():#对每一列进行异常值查找
        for c in ["风温1","风温2","风温3","炉排"]:
            dataclean(c)
    datachoice()#调用函数
    line1 = sum(line,[])
    real_time_data = real_time_data.drop(labels=line1)    #删除异常值
   # print(line1)



    #     #分特征矩阵与标签矩阵
    real_time_data2 = real_time_data.copy() #用于风温与炉排的建模
    #print(real_time_data2)


    real_time_data2.drop(["日期","炉温","排粮量","干粮水分%","原粮水分","备注","长"],inplace=True,axis=1)
    #由于这是用的历史数据存在其他参数，所以建模时需将其删除，使用时可将这行注释
    #特征矩阵为风温1，风温2，风温3；标签矩阵为炉排
    x = real_time_data2.iloc[:,real_time_data2.columns!="炉排"]
    y = real_time_data2.iloc[:,real_time_data2.columns=="炉排"]


    #分训练集与测试集
    Xtrain,Xtest,Ytrain,Ytest=train_test_split(y,x,test_size=0.3)
   # print(Xtrain)
    for i in [Xtrain, Xtest, Ytrain, Ytest]:  # 利用循环将以此转换四个矩阵,将所有的矩阵进行重新排序
        i.index = range(i.shape[0])  # range(i.shape[0])的作用是返回所有行的总数
    #print(Xtrain)


    #利用决策树建模
    tr = []  # 创建训练集列表
    te = []  # 创建测试集列表
    for i in range(10):  # 利用for循环改变不同的深度
        regr_1 = DecisionTreeRegressor(random_state=30 \
                                     , max_depth=i + 1 \
                                       # ,criterion="entropy"\
                                       )
        regr_1 = regr_1.fit(Xtrain, Ytrain)  # 训练模型
        score_tr = regr_1.score(Xtrain, Ytrain)  # 返回训练集的分数
        score_te = regr_1.score(Xtest, Ytest)
        # score_tr=cross_val_score(regr_1,x,y,cv=10).mean()
        # score_te=cross_val_score(regr_1,x,y,cv=10).mean()   #交叉验证
        tr.append(score_tr)  # 将每次的分数放到对应的列表中
        te.append(score_te)
    print(max(te), max(tr))
    plt.plot(range(1, 11), tr, color="red", label="train")  # 画折线图
    plt.plot(range(1, 11), te, color="blue", label="test")
    plt.xticks(range(1, 11))
    plt.legend()
    #plt.show()


    #利用随机森林建模
    tr1 = []  # 创建训练集列表
    te1 = []  # 创建测试集列表
    for i in range(0, 10):  # 利用for循环改变不同的深度
        regr_2 = RandomForestRegressor(n_estimators=10, random_state=0
                                          , max_depth=i
                                          )
        # cross_score = cross_val_score(regr_1,x,y, cv=10).mean()
        regr_2 = regr_2.fit(Xtrain, Ytrain)  # 训练模型
        # score_tr = cross_score
        score_tr1 = regr_2.score(Xtrain,Ytrain)  # 返回训练集的分数
        score_te1 = regr_2.score(Xtest,Ytest)
         #score_tr=cross_val_score(regr_2,x,y,cv=10).mean()
        # score_te=cross_val_score(regr_1,x,y,cv=10,scoring = "neg_mean_squared_error").mean()  #交叉验证
        tr1.append(score_tr1)  # 将每次的分数放到对应的列表中
        te1.append(score_te1)
    print(max(te1), max(tr1))
    plt.plot(range(1, 11), tr1, color="red", label="train")  # 画折线图
    plt.plot(range(1, 11), te1, color="blue", label="test")
    plt.xticks(range(1, 11))
    plt.legend()
   # plt.show()


   #利用线性模型建模
    enc = KBinsDiscretizer(n_bins=10, encode="onehot")
    X_binned = enc.fit_transform(Xtrain)
    Y_binned = enc.transform(Ytrain)

    LinearR_ = LinearRegression().fit(X_binned, Ytrain)
    line_score = LinearR_.score(Y_binned, Ytest)
    #print(line_score)






    real_time_data3 = real_time_data.copy()  # 用于排粮量与干粮水分的建模

    real_time_data3.drop(["日期", "炉温", "风温1", "风温2", "风温3","炉排","原粮水分", "备注", "长"], inplace=True, axis=1)
    # 由于这是用的历史数据存在其他参数，所以建模时需将其删除，使用时可将这行注释
    # 特征矩阵为排练量；标签矩阵为干粮水分
    x1 = real_time_data3.iloc[:, real_time_data2.columns != "排粮量"]
    y1 = real_time_data3.iloc[:, real_time_data2.columns == "排粮量"]

    # 分训练集与测试集
    Xtrain, Xtest, Ytrain, Ytest = train_test_split(y1, x1, test_size=0.3)
    # print(Xtrain)
    for i in [Xtrain, Xtest, Ytrain, Ytest]:  # 利用循环将以此转换四个矩阵,将所有的矩阵进行重新排序
        i.index = range(i.shape[0])  # range(i.shape[0])的作用是返回所有行的总数
    # print(Xtrain)

        # 利用决策树建模
        tr3 = []  # 创建训练集列表
        te3 = []  # 创建测试集列表
        for i in range(10):  # 利用for循环改变不同的深度
            regr_1 = DecisionTreeRegressor(random_state=30 \
                                          , max_depth=i + 1 \
                                           # ,criterion="entropy"\
                                           )
            regr_1 = regr_1.fit(Xtrain, Ytrain)  # 训练模型
            score_tr3 = regr_1.score(Xtrain, Ytrain)  # 返回训练集的分数
            score_te3 = regr_1.score(Xtest, Ytest)
            # score_tr=cross_val_score(regr_1,x,y,cv=10).mean()
            # score_te=cross_val_score(regr_1,x,y,cv=10).mean()   #交叉验证
            tr3.append(score_tr3)  # 将每次的分数放到对应的列表中
            te3.append(score_te3)
        print(max(te3), max(tr3))
        plt.plot(range(1, 11), tr3, color="red", label="train")  # 画折线图
        plt.plot(range(1, 11), te3, color="blue", label="test")
        plt.xticks(range(1, 11))
        plt.legend()
        # plt.show()

        # 利用随机森林建模
        tr4 = []  # 创建训练集列表
        te4 = []  # 创建测试集列表
        for i in range(0, 10):  # 利用for循环改变不同的深度
            regr_2 = RandomForestRegressor(n_estimators=10, random_state=0
                                           , max_depth=i
                                           )
            # cross_score = cross_val_score(regr_1,x,y, cv=10).mean()
            regr_2 = regr_2.fit(Xtrain, Ytrain)  # 训练模型
            # score_tr = cross_score
            score_tr4 = regr_2.score(Xtrain, Ytrain)  # 返回训练集的分数
            score_te4 = regr_2.score(Xtest, Ytest)
            # score_tr=cross_val_score(regr_2,x,y,cv=10).mean()
            # score_te=cross_val_score(regr_1,x,y,cv=10,scoring = "neg_mean_squared_error").mean()  #交叉验证
            tr4.append(score_tr4)  # 将每次的分数放到对应的列表中
            te4.append(score_te4)
        print(max(te1), max(tr1))
        plt.plot(range(1, 11), tr4, color="red", label="train")  # 画折线图
        plt.plot(range(1, 11), te4, color="blue", label="test")
        plt.xticks(range(1, 11))
        plt.legend()
    # plt.show()

    # 利用线性模型建模
    enc = KBinsDiscretizer(n_bins=10, encode="onehot")
    X_binned1 = enc.fit_transform(Xtrain)
    Y_binned1 = enc.transform(Ytrain)

    LinearR_1= LinearRegression().fit(X_binned1, Ytrain)
    line_score1 = LinearR_1.score(Y_binned1, Ytest)

    return line_score , line_score1 , max(tr) , max(te)  , max(tr1) , max(te1),max(te3),max(tr3),max(te4),max(tr4)

real_time_data1 = pd.read_excel("D:/桌面/毕业设计/最新总数据.xlsx")
modeling(real_time_data1)